﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Data;

using SSN.Utilities.Database;
using SSN.Data.Database;
using SSN.Objects;
using SSN.DotNet;
using SSN.Objects.DBPersist;
using SSN.Utilities;

namespace SSN.WebFramework
{
    /// <summary>
    /// Handles the per page security on SSNTranet/Focalweb
    /// </summary>
    public class PageSecurity : SafeDbObject
    {
        #region dbshtuff
        /// <summary>
        /// Returns the database type this object belongs to.
        /// </summary>
        public static SSNDBType DbType { get { return SSNDBType.BossSQL; } }
        protected override SSNDBType DataBaseType
        {
            get { return PageSecurity.DbType; }
        }

        /// <summary>
        /// Returns the 
        /// </summary>
        public static string TableName { get { return "web_security"; } }
        public override string DataTableName
        {
            get { return PageSecurity.TableName; }
        }

        protected override bool SetKeyFields()
        {
            Context.DataKeys["id"] = -1;
            return true;
        }

        public override string ObjectName
        {
            get { return "PagSecurity"; }
        }
        #endregion

        #region initializers
        /// <summary>
        /// Initalizes a new PageSecurity object.
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public bool New(SSNSecurityContext context)
        {
            return InitNew(context);
        }

        /// <summary>
        /// Loads the PageSecurity item with the id.
        /// </summary>
        /// <param name="context">SecurityContext</param>
        /// <param name="appName">Name of the application</param>
        /// <param name="id">Id of the PageSecurity item.</param>
        /// <returns>Whether the load was successful.</returns>
        public bool Load(SSNSecurityContext context, int id){
            return base.Load(context, new object[] { id });
        }

        /// <summary>
        /// Gets all the PageSecurity entries for a page.
        /// </summary>
        /// <param name="appName">Name of the application</param>
        /// <param name="page">The page to get the security form.</param>
        /// <returns>List of PageSecurity entries.</returns>
        public static List<PageSecurity> GetSecurityForPage(string appName, GenPage page)
        {
            return GetSecurityForPage(page.SecurityManager.SecurityContext, appName, page.Request.Url.PathAndQuery);
        }

        /// <summary>
        /// Gets all PageSecurity entries for a page.
        /// </summary>
        /// <param name="context">SecurityContext</param>
        /// <param name="path">Path of the page.</param>
        /// <returns>List of PageSecurity entries.</returns>
        public static List<PageSecurity> GetSecurityForPage(SSNSecurityContext context, string appName, string path)
        {
            return PageSecurity.DbType.CreateListFromQueryFormat<PageSecurity>(context, "SELECT * FROM {0} WHERE app_name = '{1}' AND path = '{2}'", PageSecurity.TableName, appName, PageSecurity.NormalizedPath(path));
        }

        /// <summary>
        /// Normalizes the path, removing protocol and domains.
        /// </summary>
        /// <param name="path">Path to normalize.</param>
        /// <returns></returns>
        public static string NormalizedPath(string path)
        {
            string url = path.Replace("http://", "").Replace("https://", "");
            int queryIndex = url.IndexOf("?");
            int slashIndex = url.IndexOf("/");
            if (queryIndex > -1)
            {
                path = url.Substring(slashIndex, queryIndex - slashIndex);
            }
            else if (slashIndex > -1)
            {
                path = url.Substring(slashIndex);
            }
            else
            {
                path = "/" + url;
            }

            return path;
        }


        /// <summary>
        /// Gets all PageSecurity entries for an web application.
        /// </summary>
        /// <param name="context">SecurityContext</param>
        /// <param name="appName">Name of the application</param>
        /// <returns>List of PageSecurity entries.</returns>
        public static List<PageSecurity> GetSecurityForApp(SSNSecurityContext context, string appName)
        {
            return PageSecurity.DbType.CreateListFromQueryFormat<PageSecurity>(context, "SELECT * FROM {0} WHERE app_name = '{1}' ", PageSecurity.TableName, appName);
        }
        #endregion

        #region properties
        /// <summary>
        /// Gets the id of the security entry. Column: [id]
        /// </summary>
        public int ID
        {
            get { return (int)this["id"]; }
        }

        /// <summary>
        /// Gets or sets the app name that the security applies to. Column: [app_name] (200)
        /// </summary>
        [FieldLimit(200)]
        public string AppName
        {
            get { return (string) this["app_name"]; }
            set { this["app_name"] = value; }
        }

        /// <summary>
        /// Gets or sets the path that the page is located. Column: [path] (500)
        /// </summary>
        [FieldLimit(500)]
        public string Path
        {
            get { return (string)this["path"]; }
            set { this["path"] = value; }
        }

        /// <summary>
        /// Gets or sets the information of the security entry. Column: [principle] (200)
        /// </summary>
        [FieldLimit(200)]
        public string Principle
        {
            get { return (string)this["principle"]; }
            set { this["principle"] = value; }
        }

        /// <summary>
        /// Gets or sets the type of information the principle refers to. Column: [principle_type] (200)
        /// </summary>
        public PrincipleType PrincipleType
        {
            get { return ((string)this["principle_type"]).ToEnum<PrincipleType>(); }
            set { this["principle_type"] = value.ToString(); }
        }

        /// <summary>
        /// Gets or sets the access level granted to the entry. Column: [access_level] (50)
        /// </summary>
        public AccessLevel AccessLevel
        {
            get { return ((string)this["access_level"]).ToEnum<AccessLevel>(); }
            set { this["access_level"] = value.ToString(); }
        }
        #endregion

        #region overrides
        public override string ToString()
        {
            return string.Format("{0} - {1} - {2}", PrincipleType, Principle, AccessLevel);
        }
        #endregion
    }
}
